package com.the_last.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.the_last.constant.RedisKeyConstant;
import com.the_last.mapper.OrderMapper;
import com.the_last.pojo.dto.SubmitOrderDTO;
import com.the_last.pojo.po.Order;
import com.the_last.pojo.po.OrderTable;
import com.the_last.pojo.po.Product;
import com.the_last.pojo.vo.OrderDetailVO;
import com.the_last.pojo.vo.OrderVO;
import com.the_last.pojo.vo.PageVO;
import com.the_last.service.OrderService;
import com.the_last.service.OrderTableService;
import com.the_last.service.OrderTimeoutMessageService;
import com.the_last.utils.RedisUtil;
import com.the_last.utils.Result;
import com.the_last.utils.SnowflakeIdWorker;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    
    private final OrderTableService orderTableService;
    
    private final RedisUtil redisUtil;
    
    private final RedissonClient redissonClient;
    
    private final SnowflakeIdWorker snowflakeIdWorker;
    
    private final OrderTimeoutMessageService orderTimeoutMessageService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Order> submitOrder(SubmitOrderDTO submitOrderDTO, Long userId) {
        // 1. 幂等性检查
        String orderKey = RedisKeyConstant.ORDER_SUBMIT_PREFIX + userId + submitOrderDTO.getProductQuantityJson();
        RLock idempotentLock = redissonClient.getLock(orderKey);
        
        try {
            // 尝试获取幂等性锁，如果获取不到说明是重复提交
            if (!idempotentLock.tryLock(0, 30, TimeUnit.SECONDS)) {
                throw new RuntimeException("订单正在处理中，请勿重复提交");
            }
            
            // 检查是否已经处理过
            String processedOrderId = redisUtil.get(orderKey + RedisKeyConstant.ORDER_DONE_SUFFIX);
            if (processedOrderId != null) {
                return Result.fail("请不要重复购买");
            }
            
            // 解析商品数量JSON
            JSONObject productInfo = JSON.parseObject(submitOrderDTO.getProductQuantityJson());
            
            // 获取购买锁
            RLock purchaseLock = redissonClient.getLock(RedisKeyConstant.ORDER_PURCHASE_LOCK);
            try {
                // 尝试获取购买锁
                if (!purchaseLock.tryLock(3, 10, TimeUnit.SECONDS)) {
                    throw new RuntimeException("系统繁忙，请稍后再试");
                }
                
                // 一次性获取所需的商品信息和库存信息
                Set<String> productIds = productInfo.keySet();
                Map<String, String> productJsonMap = redisUtil.hMGet(RedisKeyConstant.PRODUCT_INFO_KEY, productIds);
                Map<String, String> stockMap = redisUtil.hMGet(RedisKeyConstant.PRODUCT_STOCK_KEY, productIds);
                Map<String, String> salesMap = redisUtil.hMGet(RedisKeyConstant.PRODUCT_SALES_KEY, productIds);
                
                // 创建订单表项列表
                List<OrderTable> orderTables = new ArrayList<>();
                BigDecimal totalAmount = BigDecimal.ZERO;
                
                // 使用雪花算法生成订单ID
                long orderId = snowflakeIdWorker.nextId();
                
                // 检查商品信息和库存，在内存中处理
                for (String productId : productIds) {
                    JSONArray productData = productInfo.getJSONArray(productId);
                    String productName = productData.getString(0);
                    Integer quantity = productData.getInteger(1);
                    
                    // 检查商品信息
                    String productJson = productJsonMap.get(productId);
                    if (productJson == null) {
                        throw new RuntimeException("商品" + productName + "信息不存在");
                    }
                    Product product = JSON.parseObject(productJson, Product.class);
                    BigDecimal price = product.getCurrentPrice();
                    if (price == null) {
                        throw new RuntimeException("商品" + productName + "价格不存在");
                    }
                    
                    // 检查库存
                    String stockStr = stockMap.get(productId);
                    if (stockStr == null) {
                        throw new RuntimeException("商品" + productName + "库存信息不存在");
                    }
                    int currentStock = Integer.parseInt(stockStr);
                    if (currentStock < quantity) {
                        throw new RuntimeException("商品" + productName + "库存不足");
                    }
                    
                    // 更新库存
                    stockMap.put(productId, String.valueOf(currentStock - quantity));
                    // 更新销量
                    salesMap.put(productId, String.valueOf(Integer.parseInt(salesMap.get(productId)) + quantity));
                    
                    // 计算金额
                    BigDecimal amount = price.multiply(new BigDecimal(quantity));
                    totalAmount = totalAmount.add(amount);
                    
                    // 创建订单表项
                    OrderTable orderTable = new OrderTable();
                    orderTable.setOrderId(orderId);
                    orderTable.setProductId(Integer.valueOf(productId));
                    orderTable.setQuantity(quantity);
                    orderTable.setPurchasePrice(price);
                    orderTable.setAmount(amount.intValue());
                    
                    orderTables.add(orderTable);
                }
                
                // 创建订单
                Order order = new Order();
                order.setId(orderId);
                order.setUserId(userId);
                order.setDeliverymanId(1); // 配送员ID暂时写死为1
                order.setSubmitTime(new Date());
                order.setStatus(Order.STATUS_NOT_PAID);
                order.setTotalAmount(totalAmount);
                
                // 保存订单和订单表项
                save(order);
                if (!orderTables.isEmpty()) {
                    orderTableService.saveBatch(orderTables);
                }
                
                // 发送订单超时延迟消息
                try {
                    orderTimeoutMessageService.sendOrderTimeoutMessage(orderId);
                    log.info("订单超时消息发送成功，订单ID: {}", orderId);
                } catch (Exception e) {
                    log.error("订单超时消息发送失败，订单ID: {}", orderId, e);
                    // 不影响订单提交流程，仅记录日志
                }
                
                // 设置订单处理完成标记（用于幂等性检查）
                redisUtil.set(
                        orderKey + RedisKeyConstant.ORDER_DONE_SUFFIX,
                        String.valueOf(orderId),
                        5 * RedisUtil.ONE_SECOND
                );
                // 一次性更新所有商品的库存
                redisUtil.hMSet(RedisKeyConstant.PRODUCT_STOCK_KEY, stockMap);
                // 一次性更新所有商品的销量
                redisUtil.hMSet(RedisKeyConstant.PRODUCT_SALES_KEY, salesMap);
                return Result.success(order);
            } finally {
                if (purchaseLock.isHeldByCurrentThread()) {
                    purchaseLock.unlock();
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("订单处理被中断");
        } finally {
            if (idempotentLock.isHeldByCurrentThread()) {
                idempotentLock.unlock();
            }
        }
    }
    
    @Override
    public Result<PageVO<OrderVO>> getOrderList(Long userId, Integer status, Integer pageNum, Integer pageSize) {
        // 使用MyBatis-Plus的分页插件
        Page<OrderVO> page = new Page<>(pageNum, pageSize);
        
        // 根据状态码转换为具体状态
        String orderStatus = null;
        if (status != null && status != 0) {
            switch (status) {
                case 1:
                    orderStatus = Order.STATUS_NOT_PAID;
                    break;
                case 2:
                    orderStatus = Order.STATUS_DELIVERY;
                    break;
                case 3:
                    orderStatus = Order.STATUS_FINISHED;
                    break;
                case 4:
                    // 退款相关状态合并查询
                    orderStatus = Order.STATUS_REFUND + "," + Order.STATUS_REFUND_SUCCESS;
                    break;
                case 5:
                    orderStatus = Order.STATUS_TIMEOUT_CLOSED;
                    break;
                default:
                    break;
            }
        }
        
        // 查询订单列表
        IPage<OrderVO> pageResult = baseMapper.selectOrderList(page, userId, orderStatus);
        
        // 构建返回结果
        PageVO<OrderVO> pageVO = new PageVO<>();
        pageVO.setRecords(pageResult.getRecords());
        pageVO.setTotal(pageResult.getTotal());
        pageVO.setHasMore(pageNum < pageResult.getPages());
        
        return Result.success(pageVO);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<String> payOrder(String orderId) {
        // 获取订单信息
        Order order = getById(orderId);
        if (order == null) {
            return Result.fail("订单不存在");
        }
        
        // 检查订单状态
        if (!Order.STATUS_NOT_PAID.equals(order.getStatus())) {
            return Result.fail("订单已支付");
        }
        
        try {
            // 更新订单状态
            order.setStatus(Order.STATUS_FINISHED);
            order.setPaymentTime(new Date());
            
            // 保存订单
            updateById(order);
            
            return Result.success("支付成功");
        } catch (Exception e) {
            return Result.fail("支付失败");
        }
    }
    
    @Override
    public Result<OrderDetailVO> getOrderDetail(String orderId) {
        try {
            // 参数校验
            if (orderId == null || orderId.trim().isEmpty()) {
                return Result.fail("订单ID不能为空");
            }
            
            // 查询订单详情
            OrderDetailVO orderDetail = baseMapper.selectOrderDetail(orderId);
            if (orderDetail == null) {
                return Result.fail("订单不存在");
            }
            
            log.info("查询订单详情成功，订单ID: {}", orderId);
            return Result.success(orderDetail);
            
        } catch (Exception e) {
            log.error("查询订单详情失败，订单ID: {}", orderId, e);
            return Result.fail("查询订单详情失败：" + e.getMessage());
        }
    }
    
    @Override
    public Result<String> deleteOrder(String orderId) {
        try {
            // 检查订单是否存在
            Order order = getById(orderId);
            if (order == null) {
                return Result.fail("订单不存在");
            }
            
            // 逻辑删除订单
            removeById(orderId);
            log.info("删除订单成功，订单ID: {}", orderId);
            return Result.success("删除订单成功");
        } catch (Exception e) {
            log.error("删除订单失败，订单ID: {}", orderId, e);
            return Result.fail("删除订单失败：" + e.getMessage());
        }
    }
}